package com.reebake.ideal.permission.service.impl;

import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.reebake.ideal.permission.entity.Menu;
import com.reebake.ideal.permission.entity.MetadataSourceEntity;
import com.reebake.ideal.permission.entity.RoleMenu;
import com.reebake.ideal.permission.entity.UserRole;
import com.reebake.ideal.permission.mapper.MenuMapper;
import com.reebake.ideal.permission.mapper.PermissionAuthMapper;
import com.reebake.ideal.permission.mapper.RoleMenuMapper;
import com.reebake.ideal.permission.mapper.UserRoleMapper;
import com.reebake.ideal.permission.service.PermissionAuthService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@RequiredArgsConstructor
@Service
public class PermissionAuthServiceImpl implements PermissionAuthService {
    private final PermissionAuthMapper permissionAuthMapper;
    private final RoleMenuMapper roleMenuMapper;
    private final UserRoleMapper userRoleMapper;
    private final MenuMapper menuMapper;
    public static final String ROOT_ID = "0";

    @Override
    public List<Menu> queryMenuByUserId(String userId, String menuType) {
        List<Menu> menus = permissionAuthMapper.selectMenuByUser(userId, menuType);
        menus.removeIf(menu -> BooleanUtil.isFalse(menu.getIsLeaf()));
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getIsLeaf, false);
        List<Menu> parents = menuMapper.selectList(queryWrapper);
        Set<String> noChildIds = new HashSet<>();
        List<Menu> allMenus = new ArrayList<>();
        for(Menu parent : parents) {
            boolean found = false;
            for(Menu menu : menus) {
                if(parent.getMenuId().equals(menu.getParentId())) {
                    found = true;
                    break;
                }
            }
            if(!found){
                for(Menu p : parents) {
                    if(parent.getMenuId().equals(p.getParentId())) {
                        found = true;
                        break;
                    }
                }
            }
            if(found) {
                allMenus.add(parent);
            }
        }
        allMenus.addAll(menus);
        return allMenus;
    }

    @Override
    public Map<String, Set<String>> loadMetadata() {
        List<MetadataSourceEntity> metas = permissionAuthMapper.selectMetadata();
        Map<String, Set<String>> map = new HashMap<>();
        for(MetadataSourceEntity meta : metas){
            String path = meta.getPath();
            String authority = meta.getAuthority();
            if(!map.containsKey(path)){
                map.put(path, new HashSet<String>());
            }
            map.get(path).add(authority);
        }
        return map;
    }

    @Override
    @Transactional
    public void saveRoleMenu(String roleId, Collection<String> menuIds) {
        LambdaQueryWrapper<RoleMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RoleMenu::getRoleId, roleId);
        roleMenuMapper.delete(queryWrapper);

        List<RoleMenu> roleMenus = new ArrayList<>();
        for(String menuId : menuIds){
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(roleId);
            roleMenu.setMenuId(menuId);
            roleMenus.add(roleMenu);
        }
        roleMenuMapper.insert(roleMenus);
    }

    @Override
    @Transactional
    public void saveUserRole(String userId, Collection<String> roleIds) {
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId, userId);
        userRoleMapper.delete(queryWrapper);

        List<UserRole> userRoles = new ArrayList<>();
        for(String roleId : roleIds){
            UserRole userRole = new UserRole();
            userRole.setRoleId(roleId);
            userRole.setUserId(userId);
            userRoles.add(userRole);
        }
        userRoleMapper.insert(userRoles);
    }

    @Override
    public List<String> queryRoleCodeByUserId(String userId) {
        return permissionAuthMapper.selectRoleCodeByUser(userId);
    }

}
